<template>
  <div class="example">
    <table class="table">
      <thead class="table__thead">
        <tr>
          <th v-for="item in columns" :key="item.field" :colspan="item.colspan || 1" :rowspan="item.rowspan || 1">
            {{ item.headerName }}
          </th>
        </tr>
      </thead>
      <tbody>
        <template v-for="(item, rowIndex) in data">
          <!-- 处理行合并的情况 -->
          <tr :key="item.id">
            <td v-for="(row, colIndex) in generateData(item, rowIndex)" :key="`${rowIndex}-${colIndex}`"
              :style="row.style" :class="renderClass(row)" :rowspan="row.rowspan" :colspan="row.colspan" @click="handleRowClick(row, rowIndex)">
              {{ renderValue(row) }}
            </td>
          </tr>
        </template>
      </tbody>
    </table>
  </div>
</template>

<script lang="ts">
import { Component, Vue, Prop } from 'vue-property-decorator';
import type { ConfigItem } from '@/types/tester';

export type Columns = {
  field: string;
  headerName: string;
  style?: string;
  onClick?: (e: TableData["value"], index: number) => void;
  // 新增合并相关属性
  colspan?: number;
  rowspan?: number;
  // 合并分组标识
  mergeField?: string;
}[]

export type TableData = Partial<ConfigItem> & {
  value: string | number;
  key: string;
  label: string;
  style?: string;
  onClick?: (row: TableData["value"], index: number) => void;
  // 新增合并相关属性
  rowspan?: number;
  colspan?: number;
  // 合并分组标识
  mergeId?: string | number;
  field?: string;
  placeholder?: string;
}

@Component
export default class Table extends Vue {
  @Prop({ type: Array, default: () => [] }) columns!: Columns;
  @Prop({ type: Array, default: () => [] }) data!: Record<string, any>[];

  // 存储合并信息
  private mergeInfo: Map<string, { rowspan: number, colspan: number }> = new Map();

  created() {
    this.calculateMergeInfo();
  }

  renderValue(row: TableData) {
    if (row.value !== '-') return row.value;
    if (row.placeholder) return row.placeholder;
    return row.value;
  }

  renderClass(row: TableData) {
    if (row.value === '-' && row.placeholder) return 'table__placeholder';
    return '';
  }

  // 计算需要合并的单元格信息
  calculateMergeInfo() {
    this.mergeInfo.clear();

    // 处理列合并
    this.columns.forEach(col => {
      if (col.mergeField) {
        let count = 1;
        let lastValue: any = null;

        this.data.forEach((item, index) => {
          const currentValue = item[col.mergeField as string];

          if (currentValue === lastValue) {
            count++;
            // 标记前一个单元格需要增加rowspan
            const prevKey = `${index - count + 1}-${col.field}`;
            const info = this.mergeInfo.get(prevKey) || { rowspan: 1, colspan: 1 };
            info.rowspan = count;
            this.mergeInfo.set(prevKey, info);

            // 标记当前单元格不显示
            const currentKey = `${index}-${col.field}`;
            this.mergeInfo.set(currentKey, { rowspan: 0, colspan: item.colspan || 0 });
          } else {
            count = 1;
            lastValue = currentValue;
          }
        });
      } else {
        this.data.forEach((item, index) => {
          const currentKey = `${index}-${col.field}`;
          this.mergeInfo.set(currentKey, { rowspan: 1, colspan: item.colspan || 1 });
        });
      }
    });
  }

  /**
   * Generates table data with merge information for a given row item.
   *
   * 此函数处理单行数据并返回一个 TableData 对象数组，每个对象代表一个表格单元格。
   * 它考虑了存储在 mergeInfo 中的合并信息，以确定每个单元格的适当行跨度和列跨度。
   */
  generateData(item: Record<string, any>, rowIndex: number): Array<TableData> {
    const result: Array<TableData> = [];

    for (const [key, value] of Object.entries(item)) {
      const colIndex = this.columns.findIndex(col => col.field === key);
      if (colIndex !== -1) {
        const column = this.columns[colIndex];
        const cellKey = `${rowIndex}-${key}`;
        const mergeInfo = this.mergeInfo.get(cellKey) || { rowspan: 1, colspan: 1 };

        result[colIndex] = {
          ...item,
          key: item.key,
          label: item.label,
          value,
          onClick: column.onClick,
          rowspan: mergeInfo.rowspan,
          colspan: column.colspan || mergeInfo.colspan,
          mergeId: column.mergeField ? item[column.mergeField] : undefined,
          field: key
        };
      }
    }
    return result;
  }

  handleRowClick(row: any, rowIndex: number) {
    this.$emit('row-click', row, rowIndex);
  }
}
</script>

<style lang="scss" scoped>
$borderRadius: 6px;
$borderColor: #ddd;
$thColor: rgba(207, 226, 255, 0.2);

.table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  width: 100%;
  font-size: 14px;
  color: #333333;
}

.table__thead th {
  background-color: $thColor;
  padding: 8px;
  text-align: center;
  border-bottom: 1px solid $borderColor;
  border-right: 1px solid $borderColor;
}

.table td {
  padding: 8px;
  border-bottom: 1px solid $borderColor;
  border-right: 1px solid $borderColor;
}

/* 被合并的单元格隐藏 */
.table td[rowspan="0"],
.table td[colspan="0"] {
  display: none;
}

tr td:last-child,
tr th:last-child {
  border-right: 0;
}

.table__placeholder {
  color: #c2c3c2;
}
</style>
